import Squeezebox
import FrameBuffer
from utils import *
import pygame
from pygame.locals import *
import sys
import urllib2
import uuid
import time
from time import sleep

if isPi():
    logging.debug('Running on Raspberry Pi')
    import gaugette.rotary_encoder 
    import wiringpi2 as wiringpi
else:
    logging.debug('Not Running on Raspberry Pi')
    
class Streamer( object ):

    def __init__(self):
        
        self.f = FrameBuffer.FrameBuffer()
        #self.f.drawSplash()
        self.f.setMenu(name='topMenu', menuList=self.f.topMenuList, menuID=range(len(self.f.topMenuList)), key='')

        
        self.config = loadConfigFile()
        self.s = Squeezebox.Squeezebox(host=self.config['Squeezebox']['serverIP'],
                                       port = self.config['Squeezebox']['serverPort'], 
                                       player_id=self.config['Squeezebox']['playerMAC'])
        
        self.serverError()  
                    
        self.artistAlbumsArtist=''
        self.albumName=''
        
    def serverError(self):
        self.f.drawNotificationScreen("Connecting to server")
        if self.s.connectToServer():
            self.f.drawNotificationScreen("Connecting to player")
            if not self.s.connectToLocalPlayer():
                self.f.drawNotificationScreen("Failed to connect to player")
                sleep(1)            
        else:
            self.f.drawNotificationScreen("Failed to connect to server")
            sleep(1)
        self.f.setMenu(name='topMenu', menuList=self.f.topMenuList, menuID=range(len(self.f.topMenuList)), key='')
        
         
    def setScreen(self, type, name, idFromChild=[]):
        
        if type =='menu':
            menuList=[]
            menuID=[]
            key = ''
                
            if name == 'topMenu':
                menuList=self.f.topMenuList
                menuID=range(len(self.f.topMenuList))
            elif name == 'allArtists':
                a=self.s.getArtists()                
                if a:
                    for n in range(len(a)):
                        menuList.append(a[n]['artist'])
                        menuID.append(a[n]['id'])
                    self.backScreen=['menu','topMenu']
                else:
                    self.serverError()
                    return
            elif name == 'allAlbums':
                a=self.s.getAlbums()
                for n in range(len(a)):
                    menuList.append(a[n]['album'])
                    menuID.append(a[n]['id'])
            elif name == 'allPlaylists':
                a=self.s.getPlaylists()
                for n in range(len(a)):
                    menuList.append(a[n]['playlist'])
                    menuID.append(a[n]['id'])
            elif name == 'playlistTracks':
                playlistID = self.f.menuID[self.f.selectedIndex]
                a=self.s.getPlaylist(playlistID)
                menuList.append('Play All')
                menuID.append(playlistID)
                for n in range(len(a)):
                    menuList.append(a[n]['title'])
                    menuID.append(a[n]['id'])
            elif name == 'artistAlbums':
                if idFromChild:
                    artistID=idFromChild
                else:                    
                    artistID = self.f.menuID[self.f.selectedIndex]
                a = self.s.getArtistAlbums(artistID)
                for n in range(len(a)):
                    menuList.append(a[n]['album'])
                    menuID.append(a[n]['id'])
                self.artistAlbumsArtist=artistID
            elif name == 'albumsAlbum':
                if idFromChild:
                    albumID=idFromChild
                else:                    
                    albumID = self.f.menuID[self.f.selectedIndex]
                    #print albumID
                a = self.s.getAlbum(albumID)
                for n in range(len(a)):
                    menuList.append(a[n]['title'])
                    menuID.append(a[n]['id'])
            elif name == 'artistAlbumsAlbum':
                albumID = self.f.menuID[self.f.selectedIndex]
                self.albumParent = albumID
                #print self.albumParent
                a = self.s.getAlbum(albumID)
                menuList.append('Play All')
                menuID.append(albumID)
                for n in range(len(a)):
                    menuList.append(a[n]['title'])
                    menuID.append(a[n]['id'])
            elif name == 'que':
                a=self.s.getQue()
                #print a[1]['id']
                for n in range(len(a)):
                    menuList.append(a[n]['title'])
                    menuID.append(a[n]['id'])
                    print a[n]['title']
            
            self.f.setMenu(name, menuList, menuID, key)
        elif type =='info':
            if name == 'nowPlaying':               
                self.f.drawNowPlayingScreen(self.s.getCoverURL())
        
        
    def enterCallback(self):
        #print "Enter"
        if self.f.screenType == 'menu':
            if self.f.screenName == 'topMenu':
                if self.f.topMenuList[self.f.selectedIndex] == 'Now Playing':
                    self.setScreen('info','nowPlaying')
                if self.f.topMenuList[self.f.selectedIndex] == 'Artists':
                    self.setScreen('menu','allArtists')
                elif self.f.topMenuList[self.f.selectedIndex] == 'Albums':
                    self.setScreen('menu','allAlbums')
                elif self.f.topMenuList[self.f.selectedIndex] == 'Playlists':
                    self.setScreen('menu','allPlaylists')
                elif self.f.topMenuList[self.f.selectedIndex] == 'Exit':
                    logging.debug("Exiting application")
                    pygame.quit()
                    sys.exit()
            # top menu -> all artists -> artist
            elif self.f.screenName == 'allArtists':
                self.setScreen('menu','artistAlbums')
            # top menu -> all artists -> artist -> album
            elif self.f.screenName == 'artistAlbums':
                self.setScreen('menu','artistAlbumsAlbum')
             # top menu -> all albums -> album
            elif self.f.screenName == 'allAlbums':
                self.setScreen('menu','albumsAlbum')
            # top menu -> all artists -> artist -> album -> track
            elif self.f.screenName == 'artistAlbumsAlbum':
                print "index: %s" % self.f.menuID[self.f.selectedIndex]
                if self.f.menuList[self.f.selectedIndex] == 'Play All':
                    #play album
                    print 'hero'
                    albumID=self.f.menuID[self.f.selectedIndex]
                    self.s.playAlbum(albumID)
                else:
                    #play track    
                    trackID = self.f.menuID[self.f.selectedIndex]
                    print trackID
                    self.s.playTrack(trackID)
                self.setScreen('info','nowPlaying')
            # top menu -> all playlists -> playlist -> track
            elif self.f.screenName == 'playlistTracks':
                #print "index: %s" % self.f.menuID[self.f.selectedIndex]
                if self.f.menuList[self.f.selectedIndex] == 'Play All':
                    playlistID=self.f.menuID[self.f.selectedIndex]
                    self.s.playPlaylist(playlistID)
                else:
                    #play track    
                    trackID = self.f.menuID[self.f.selectedIndex]
                    print trackID
                    self.s.playTrack(trackID)
                self.setScreen('info','nowPlaying')
            # top menu -> all albums -> album -> track
            elif self.f.screenName == 'albumsAlbum':
                trackID = self.f.menuID[self.f.selectedIndex]
                #print trackID
                self.s.playTrack(trackID)
                self.setScreen('info','nowPlaying')
            # top menu -> allPlaylists -> playlistTracks
            elif self.f.screenName == 'allPlaylists':
                self.setScreen('menu','playlistTracks')
        
        elif self.f.screenType == 'info':
            if self.f.screenName == 'nowPlaying':
                self.setScreen('menu','que')
            
            
        
    def backCallback(self):
        print "Back"
        if self.f.screenType == 'menu':
            if self.f.screenName == 'topMenu':
                self.setScreen('info','nowPlaying')
            elif self.f.screenName == 'allArtists':
                self.setScreen('menu','topMenu')
            elif self.f.screenName == 'allAlbums':
                self.setScreen('menu','topMenu')
            elif self.f.screenName == 'allPlaylists':
                self.setScreen('menu','topMenu')
            elif self.f.screenName == 'artistAlbums':
                self.setScreen('menu','allArtists')
            elif self.f.screenName == 'artistAlbumsAlbum':
                self.setScreen('menu','artistAlbums',self.artistAlbumsArtist)
            elif self.f.screenName == 'albumsAlbum':
                self.setScreen('menu','allAlbums')
            elif self.f.screenName == 'playlistTracks':
                self.setScreen('menu','allPlaylists') 
            elif self.f.screenName == 'que':
                self.setScreen('info','nowPlaying')    
        elif self.f.screenType == 'info':
            if self.f.screenName == 'nowPlaying':
                self.setScreen('menu','topMenu')
            
                
        #print self.f.screenName
        #print self.f.history[self.f.screenName]
        #type = self.f.history[self.f.screenName]['previousScreenType']
        #name = self.f.history[self.f.screenName]['previousScreenName']        
        #print type
        #print name
        #self.setScreen(type, name)
                    
        
    def upCallback(self):
        #print "Up"
        if self.f.screenType == 'menu':
            self.f.selectedRow=self.f.selectedRow-1
            self.f.drawMenu()
        else:
            print 'Currently nothing happens if you scroll unless on a menu screen'
    
    def downCallback(self):
        #print "Down"
        if self.f.screenType == 'menu':
            self.f.selectedRow=self.f.selectedRow+1
            self.f.drawMenu()
        else:
            print 'Currently nothing happens if you scroll unless on a menu screen'
            
    def previousCallback(self):
        #print "p"
        self.s.previousSong()
        
    def nextCallback(self):
        #print "n"
        self.s.nextSong()
    
    def playPauseCallback(self):
        print 'play/pause'
        self.s.playPause()
    def volumeDownCallback(self):
        v=self.s.getVolume()['_volume']
        v=int(v)-1
        self.s.setVolume(v)
        #print self.s.getVolume()['_volume']
        self.f.drawVolumePopup(self.s.getVolume()['_volume'])
    def volumeUpCallback(self):
        v=self.s.getVolume()['_volume']
        v=int(v)+1
        self.s.setVolume(v)
        #print self.s.getVolume()['_volume']
        self.f.drawVolumePopup(self.s.getVolume()['_volume'])
    def muteCallback(self):
        if self.s.getMuting()==True:
            self.s.setMuting(False)
        else:
            self.s.setMuting(True)    
        #print 'muting', self.s.getMuting()  
    def shuffleCallback(self):
        if self.s.getShuffle()==True:
            self.s.setShuffle(False)
        else:
            self.s.setShuffle(True)    
        #print 'shuffle:', self.s.getShuffle()  
        
    # Timer to clear popups
    popupClockEvent = pygame.USEREVENT    
    popupDuration = 1500
    # Timer to switch on/off amps and squeezlite
    silenceClockEvent = pygame.USEREVENT    
    silenceDuration = 60000
    # Timer for LED checks
    ledCheckClockEvent = pygame.USEREVENT
    ledCheckDuration = 1000

    # Button & encoder variables
    volume1_PIN = 21
    volume2_PIN = 22
    scroll1_PIN = 23
    scroll2_PIN = 24
    
    # Initialise buttons & rotary encoders
    if isPi():
        wiringpi.wiringPiSetup()
        wiringpi.pinMode(25, 0) # select button - replace pin num with variable
    	wiringpi.pullUpDnControl(25,2) # activate internal pullup
    	wiringpi.pinMode(26, 0) # back button
    	wiringpi.pullUpDnControl(26,2) # activate internal pullup
        # Set button GPIOs as inputs
        wiringpi.pinMode(15, 0) # previous
        wiringpi.pinMode(16, 0) # play/pause
        wiringpi.pinMode(4, 0) # next
        wiringpi.pinMode(5, 0) # mute
        wiringpi.pinMode(7, 0) # shuffle
        # Workaround for hardware bug in which pins 4,5 & 7 are not being pulled up. So activate internal pullups
        # Better check this next time the case is open.
        #wiringpi.pullUpDnControl(4,2)
        #wiringpi.pullUpDnControl(5,2)
        #wiringpi.pullUpDnControl(7,2)
        # Set LED GPIOs to outputs and low
        wiringpi.pinMode(2, 1) # Mute LED
        wiringpi.digitalWrite(2, 0) # LED Off 
        wiringpi.pinMode(3, 1) # Shuffle LED
        wiringpi.digitalWrite(3, 0) # LED Off 
    	
        volumeEncoder = gaugette.rotary_encoder.RotaryEncoder.Worker(volume1_PIN, volume2_PIN)
        scrollEncoder = gaugette.rotary_encoder.RotaryEncoder.Worker(scroll1_PIN, scroll2_PIN)
        volumeEncoder.start()
        scrollEncoder.start()

        
    def runLoop(self):
        #===============================================================================
        # Main loop
        #===============================================================================
        running = True
        while running:
            if isPi():
                volumeDelta = self.volumeEncoder.get_delta()
                scrollDelta = self.scrollEncoder.get_delta()
                if wiringpi.digitalRead(25) == 0:
                    self.enterCallback()
                    #lame debounce
                    time.sleep(0.5)
                if wiringpi.digitalRead(26) == 0:
                    self.backCallback()
                    time.sleep(0.5)
                #if wiringpi.digitalRead(15) == 0:
                #    self.previousCallback()
                #    time.sleep(0.5)
                if wiringpi.digitalRead(16) == 0:
                    self.playPauseCallback()
                    time.sleep(0.5)
                if wiringpi.digitalRead(4) == 0:
                    self.nextCallback()
                    time.sleep(0.5)
                if wiringpi.digitalRead(5) == 0:
                    self.muteCallback()
                    time.sleep(0.5)
                #if wiringpi.digitalRead(7) == 0:
                #    self.shuffleCallback()
                #    time.sleep(0.5)
                if volumeDelta==-1:
                    self.volumeDownCallback()
                    pygame.time.set_timer(self.popupClockEvent, self.popupDuration)
                    # Crude experimental debounce
                    time.sleep(0.1)
                elif volumeDelta==1:
                    self.volumeUpCallback()
                    pygame.time.set_timer(self.popupClockEvent, self.popupDuration)
                    # Crude experimental debounce
                    time.sleep(0.1)
                if scrollDelta==-1:
                    self.upCallback()
                    # Crude experimental debounce
                    time.sleep(0.1)
                elif scrollDelta==1:
                    self.downCallback()
                    # Crude experimental debounce
                    time.sleep(0.1)
                # LEDs
                #for event in pygame.event.get():
                    #if event.type == self.ledCheckClockEvent:  
                        #if self.s.getMuting()==True:
                                #self.mcp.output(14, 1)
                        #else:
                                #self.mcp.output(14, 0)
                        #pygame.time.set_timer(self.ledCheckClockEvent, 0)   
                #if self.s.getShuffle()==True:
                    #self.mcp.output(15, 1)
                #else:
                    #self.mcp.output(15, 0)                

            for event in pygame.event.get():
                #Update display to clear any popups
                if event.type == self.popupClockEvent:  
                    self.f.drawMenu()
                    pygame.time.set_timer(self.popupClockEvent, 0)
                    
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                    running = False
                #if event.type == MOUSEBUTTONDOWN and event.button == 5:
                if event.type == KEYDOWN and event.key == K_DOWN:
                    self.downCallback()
                #if event.type == MOUSEBUTTONDOWN and event.button == 4:
                if event.type == KEYDOWN and event.key == K_UP:
                    self.upCallback()    
                if event.type == KEYDOWN and event.key == K_RIGHT:
                    self.enterCallback()
                if event.type == KEYDOWN and event.key == K_LEFT:
                    self.backCallback()
                if event.type == KEYDOWN and event.key == K_n:
                    self.nextCallback()
                if event.type == KEYDOWN and event.key == K_p:
                    self.previousCallback()
                if event.type == KEYDOWN and event.key == K_SPACE:
                    self.playPauseCallback()
                if event.type == KEYDOWN and event.key == K_MINUS:
                    self.volumeDownCallback()
                    pygame.time.set_timer(self.popupClockEvent, self.popupDuration)    
                if event.type == KEYDOWN and event.key == K_EQUALS:
                    self.volumeUpCallback()
                    pygame.time.set_timer(self.popupClockEvent, self.popupDuration)
                if event.type == KEYDOWN and event.key == K_m:
                    self.muteCallback()
                if event.type == KEYDOWN and event.key == K_s:
                    self.shuffleCallback()


if __name__ == '__main__':
    s = Streamer()
    s.runLoop()
